Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for response multiValueHeaders locally #842

Closed

Conversation

martysweet
Copy link

Issue #, if available:
Addresses is #830, supporting multiValueHeaders locally.

Description of changes:

Merges lamdba response headers and multiValueHeaders in accordance with guidance from here.
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format

  • You can use the multiValueHeaders key to specify all of your extra headers, including any single-value ones.
  • If you specify values for both headers and multiValueHeaders, API Gateway merges them into a single list.
  • If the same key-value pair is specified in both, only the values from multiValueHeaders will appear in the merged list.

Within base64 logic, splits Content-Type by ;, to prevent issues with malformed Content types.
content_type = lamba_response_headers['Content-Type'].split(";", 1)[0]

  • TODO: Add tests for the _should_base64_decode_body change - Guidance needed

Checklist:

  • Write unit tests (Tests for functionality of merger and update to parse_lambda tests for ensuring the component is called)
  • Write/update functional tests (Unsure what to add - Guidance needed)
  • Write/update integration tests (Unsure what to add - Guidance needed)
  • make pr passes
  • [x ] Write documentation - No adjustment required (unless there is a supported features list somewhere?)

Please let me know what else is required/missing! 馃槃 This PR plays well with #741, which is for requests.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@martysweet
Copy link
Author

Hi @jfuss, could you let me know what else is required for this? Thanks!

@jfuss
Copy link
Contributor

jfuss commented Jan 18, 2019

@martysweet Apologies on the slow response here. I am talking a look at this now.

@jfuss jfuss self-requested a review January 18, 2019 16:46
@jfuss jfuss self-assigned this Jan 18, 2019
@jfuss jfuss added the area/local/start-api sam local start-api command label Jan 18, 2019
Copy link
Contributor

@jfuss jfuss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a couple comments to help simplify the code further.


# Get the first part of the content-type header, to allow for extras such as text/html; charset=utf-8
content_type = lamba_response_headers['Content-Type'].split(";", 1)[0]
best_match_mimetype = flask_request.accept_mimetypes.best_match([content_type])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you validate this is the correct behavior?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A MIME type should contain only type/subtype.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types

However, the Content-Type header contains the MIME, then potentially extra charset information:
https://www.ietf.org/rfc/rfc2045.txt (page 12)

In the Augmented BNF notation of RFC 822, a Content-Type header field
value is defined as follows:

 content := "Content-Type" ":" type "/" subtype
            *(";" parameter)
            ; Matching of media type and subtype
            ; is ALWAYS case-insensitive.

Passing this extra charset information into flask_request.accept_mimetypes.best_match results in Flask returning 500.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martysweet I should have been a little clearer. Does this behavior match API Gateway's? Meaning do they only look at the first Content-Type Header or do they compare with the list of all headers? Did we match documentation or what is observed from the service?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfuss Ah understood. Looking into it, this might be more complex than just looking at Content-Type, though a bit outside of this PR.

So your question is, if multiple Content-Type Headers are returned to API Gateway, which one is used for the comparison against the binary types list?

I can't find anything in the docs, will have to run some tests.

Docs regarding Accept and Content-Type (which doesn't answer the question).
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-configure-with-console.html
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-workflow.html

samcli/local/apigw/local_apigw_service.py Outdated Show resolved Hide resolved
samcli/local/apigw/local_apigw_service.py Outdated Show resolved Hide resolved
samcli/local/apigw/local_apigw_service.py Outdated Show resolved Hide resolved
samcli/local/apigw/local_apigw_service.py Outdated Show resolved Hide resolved
@everyonce
Copy link

@martysweet I really would love for this to work. when I'm testing it using both your branch here, and apigw, they do act different. this code creates a comma-seperated list in a single header (which chrome, at least, doesnt like), and apigw creates multiple headers with the same key (in my tests I'm using set-cookie, but I'm sure it's for anything that it applies to)

@dsanders11
Copy link
Contributor

and apigw creates multiple headers with the same key (in my tests I'm using set-cookie, but I'm sure it's for anything that it applies to)

@everyonce, this isn't true, actually. Set-Cookie is a special case, according to the HTTP spec headers aren't supposed to appear multiple times, but they allow Set-Cookie since it's different. API GW seems to follow this as well, only creating multiple headers for Set-Cookie and instead creating a list for other headers, like X-Foo. I've just tested it and using X-Foo definitely creates a comma-separated list.

@martysweet
Copy link
Author

Closing in favour of #1166

@martysweet martysweet closed this May 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/local/start-api sam local start-api command
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants